package com.example.demo.service.impl;

import com.example.demo.entity.Instorage;
import com.example.demo.entity.Outstorage;
import com.example.demo.entity.Storage;
import com.example.demo.mapper.OutstorageMapper;
import com.example.demo.service.InstorageService;
import com.example.demo.service.OutstorageService;
import com.example.demo.service.StorageService;
import com.example.demo.service.helper.StorageInventory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class OutstorageServiceImpl implements OutstorageService {

    @Autowired
    private OutstorageMapper outstorageMapper;

    @Autowired
    private InstorageService instorageService;

    @Autowired
    private StorageService storageService;

    @Override
    public int createOutstorage(Outstorage outstorage) {
        // 检查仓库库存是否足够
        StorageInventory inventory = instorageService.getStorageInventory(outstorage.getOsbelong());
        if (inventory.getTotalWeight() < outstorage.getOweight() ||
                inventory.getTotalQuantity() < outstorage.getOquantity()) {
            throw new RuntimeException("仓库库存不足");
        }

        // 计算堆存费
        try {
            outstorage.setOfee(calculateAndSaveStorageFee(outstorage));
        } catch (ParseException e) {
            throw new RuntimeException("日期格式错误", e);
        }

        int result = outstorageMapper.createOutstorage(outstorage);

        if (result > 0) {
            // 更新仓库库存
            Storage storage = storageService.findStorageById(outstorage.getOsbelong());
            storage.setSweight(storage.getSweight() - outstorage.getOweight());
            storage.setSquantity(storage.getSquantity() - outstorage.getOquantity());
            storageService.updateStorage(storage);
        }

        return result;
    }

    @Override
    public int deleteOutstorage(Integer oid) {
        Outstorage outstorage = outstorageMapper.findOutstorageById(oid);
        if (outstorage == null) {
            throw new RuntimeException("出库记录不存在");
        }

        int result = outstorageMapper.deleteOutstorage(oid);

        if (result > 0) {
            // 更新仓库库存
            Storage storage = storageService.findStorageById(outstorage.getOsbelong());
            storage.setSweight(storage.getSweight() + outstorage.getOweight());
            storage.setSquantity(storage.getSquantity() + outstorage.getOquantity());
            storageService.updateStorage(storage);
        }

        return result;
    }

    @Override
    public Outstorage findOutstorageById(Integer oid) {
        return outstorageMapper.findOutstorageById(oid);
    }

    @Override
    public List<Outstorage> findAllOutstorages() {
        return outstorageMapper.findAllOutstorages();
    }

    @Override
    public List<Outstorage> findOutstoragesByStorageId(Integer sid) {
        return outstorageMapper.findOutstoragesByStorageId(sid);
    }

    @Override
    public double calculateAndSaveStorageFee(Outstorage outstorage) throws ParseException {
        List<Instorage> instorages = instorageService.findInstoragesByStorageId(outstorage.getOsbelong());
        double cost = 0;
        double outWeight = outstorage.getOweight();

        for (Instorage instorage : instorages) {
            double realWeight = instorageService.getRealWeight(instorage.getIid());

            if (outWeight == 0) break;
            if (realWeight == 0) continue;

            double inWeight = realWeight;

            if (inWeight < outWeight) {
                outWeight -= inWeight;
                double temp = inWeight;
                inWeight = 0;
                instorageService.updateRealWeight(instorage.getIid(), inWeight);
                long days = getIntervalDays(instorage.getItime(), outstorage.getOtime());

                if (days >= 15) {
                    cost += temp * 0.5 * (days - 14);
                }
            } else {
                double temp = outWeight;
                inWeight -= temp;
                outWeight = 0;
                instorageService.updateRealWeight(instorage.getIid(), inWeight);
                long days = getIntervalDays(instorage.getItime(), outstorage.getOtime());

                if (days >= 15) {
                    cost += temp * 0.5 * (days - 14);
                }
            }
        }

        outstorage.setOfee(cost);
        outstorageMapper.updateStorageFee(outstorage.getOid(), cost);

        return cost;
    }

    private long getIntervalDays(Date startDate, Date endDate) {
        long diff = endDate.getTime() - startDate.getTime();
        return diff / (1000 * 60 * 60 * 24);
    }

    @Override
    public List<Outstorage> findOutstoragesByDateRange(Date startDate, Date endDate) {
        return outstorageMapper.findAllOutstorages().stream()
                .filter(o -> !o.getOtime().before(startDate) && !o.getOtime().after(endDate))
                .collect(Collectors.toList());
    }

    @Override
    public List<Outstorage> findOutstoragesByCompany(Integer cid) {
        return outstorageMapper.findAllOutstorages().stream()
                .filter(o -> {
                    Storage storage = storageService.findStorageById(o.getOsbelong());
                    return storage != null && cid.equals(storage.getScbelong());
                })
                .collect(Collectors.toList());
    }
}